/*
 * pwm.c
 *
 * Smart PWM using timer2's CC0~CC3.
 *
 * Copyright (C) 2022 Microwell, Inc.
 * Subject to the GNU Public License, version 2.
 *
 * Author: guoming<guoming@microwell.net>
 */
#include "pwm.h"
#include "core.h"

#if(PWM_CHANNEL_MODE)
void pwm_init(void)
{
    /**
     * @brief pwm must first set polarity, then set frequency, then set duty
     * last enable
     * 
     */
#if(PWM_CHANNEL_MODE & PWM0)
    pwm_set_polarity(PWM0, 1);
    // PWM0_FREQ_SET(20000);
    // PWM0_FREQ_DUTY_SET(20000, 50);
    pwm_set_duty(PWM0, 50);
    /// pwm disable
    pwm_io_disable(PWM0);
#endif
#if(PWM_CHANNEL_MODE & PWM1)
    pwm_set_polarity(PWM1, 1);
    // pwm_set_duty(50);
    // PWM1_FREQ_DUTY_SET(20000, 50);
    pwm_set_duty(PWM1, 50);
    /// pwm disable
    pwm_io_disable(PWM1);
#endif
}

/*
 * pwm, PWM ID, please refer to pwm.h
 * polarity: 1, high active; 0, low active
 */
void pwm_set_polarity(uint8_t pwm, uint8_t polarity)
{
    if(pwm == PWM0) {
        PWM0_POLARITY_SET(polarity);
    } else {
        PWM1_POLARITY_SET(polarity);
    }
}

/*
 * MAX_VAL is timer max value
 * Duty cycle ranges from 0 to 100
 */
void pwm_set_duty(uint8_t pwm, uint16_t duty)
{
    if(pwm == PWM0) {
        PWM0_DUTY_SET(duty);  
    } else {
        PWM1_DUTY_SET(duty);
    }
}

/*
 * MAX_VAL is timer max value
 * Duty cycle ranges from 0 to 100
 * freq 
 */
void pwm_set_duty_according_freq(uint8_t pwm, uint16_t duty, uint32_t freq)
{
    if(pwm == PWM0) {
        PWM0_DUTY_SET_A_FREQ(duty, freq);  
    } else {
        PWM0_DUTY_SET_A_FREQ(duty, freq);
    }
}

void pwm_exit(void)
{
#if(PWM_CHANNEL_MODE & PWM0)
    /// pwm disable
    _P00_IO_MODE();
    _P00_IO_INPUT();
    TIMER_0_DISABLE();
    PWM0_MODE_ENABLE(RESET);
#endif
#if(PWM_CHANNEL_MODE & PWM1)
    /// pwm disable
    #if(GPIO_P01_PWM_MODE == PWM1)
        _P01_IO_MODE();
        _P01_IO_INPUT();
        TIMER_1_DISABLE();
        PWM1_MODE_ENABLE(RESET);
    #endif
    #if(GPIO_P13_PWM_MODE == PWM1)
        _P13_IO_MODE();
        _P13_IO_INPUT();
        TIMER_1_DISABLE();
        PWM1_MODE_ENABLE(RESET);
    #endif
    #if(GPIO_P16_PWM_MODE == PWM1)
        _P16_IO_MODE();
        _P16_IO_INPUT();
        TIMER_1_DISABLE();
        PWM1_MODE_ENABLE(RESET);
    #endif
#endif
}

void pwm_io_enable(uint8_t pwm)
{
    if(pwm == PWM0) {
        #if(GPIO_P00_PWM_MODE == PWM0)
            /// pwm enable
            _P00_IO_PWM0();
            TIMER_0_ENABLE();
            PWM0_MODE_ENABLE(SET);   
        #endif     
    } else {
        #if(GPIO_P01_PWM_MODE == PWM1)
            _P01_IO_PWM1();
            TIMER_1_ENABLE();
            PWM1_MODE_ENABLE(SET);   
        #endif
        #if(GPIO_P13_PWM_MODE == PWM1)
            _P13_IO_PWM1();
            TIMER_1_ENABLE();
            PWM1_MODE_ENABLE(SET);   
        #endif
        #if(GPIO_P16_PWM_MODE == PWM1)
            _P16_IO_PWM1();
            TIMER_1_ENABLE();
            PWM1_MODE_ENABLE(SET);   
        #endif
    }
}

void pwm_io_disable(uint8_t pwm)
{
    if (pwm == PWM0)
    {
        #if(GPIO_P00_PWM_MODE == PWM0)
            _P00_IO_MODE();
            _P00_IO_INPUT();
            TIMER_0_DISABLE();
            PWM0_MODE_ENABLE(RESET);
        #endif
    } else {
        #if(GPIO_P01_PWM_MODE == PWM1)
            _P01_IO_MODE();
            _P01_IO_INPUT();
            TIMER_1_DISABLE();
            PWM1_MODE_ENABLE(RESET);
        #endif
        #if(GPIO_P13_PWM_MODE == PWM1)
            _P13_IO_MODE();
            _P13_IO_INPUT();
            TIMER_1_DISABLE();
            PWM1_MODE_ENABLE(RESET);
        #endif
        #if(GPIO_P16_PWM_MODE == PWM1)
            _P16_IO_MODE();
            _P16_IO_INPUT();
            TIMER_1_DISABLE();
            PWM1_MODE_ENABLE(RESET);
        #endif
    }
    

}

void pwm_io_set_freq(uint8_t pwm, uint32_t freq)
{
    if(pwm == PWM0) {
        TIMER0_FREQ_SET(freq);
    } else {
        TIMER1_FREQ_SET(freq);
    }
}

uint16_t pwm_io_get_max_duty(uint8_t pwm)
{
    if(pwm == PWM0) {
        return (TIMER0_MAX_VAL - PWM0_DUTY_READ() - 1);
    } else {
        return (TIMER1_MAX_VAL - PWM0_DUTY_READ() - 1);
    }
}
#endif